<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Style-Type" content="text/css" />
  <meta name="generator" content="pandoc" />
  <title>git的使用方法</title>
  <style type="text/css">code{white-space: pre;}</style>
  <style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
  margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
  </style>
  <link rel="stylesheet" href="doc/linux-style.css" type="text/css" />
</head>
<body>
<div id="header">
<h1 class="title">git的使用方法</h1>
</div>
<div id="TOC">
<ul>
<li><a href="#git的使用方法">git的使用方法</a></li>
</ul>
</div>
<h1 id="git的使用方法">git的使用方法</h1>
<p><a href="https://www.runoob.com/git/git-tutorial.html">Git菜鸟教程</a></p>
<p><strong>推荐一个登陆git网站的好用的工具</strong> <a href="https://steampp.net/">Steam++</a></p>
<p>听这个名字就知道，之前一直用这个软件去登陆steam商店，偶然发现还能加速GitHub，免费且流畅</p>
<ul>
<li>常用git命令：</li>
</ul>
<div class="sourceCode"><pre class="sourceCode sh"><code class="sourceCode bash"><span class="fu">git</span> init            #在当前目录初始化 Git 仓库
<span class="fu">git</span> log         #查看提交历史 --oneline（简洁显示）、-p（显示差异）
<span class="fu">git</span> status      #查看工作区状态（修改/未跟踪的文件）
<span class="fu">git</span> add <span class="op">&lt;</span>file<span class="op">&gt;</span>      #将文件添加到暂存区  git add .（添加所有文件）
<span class="fu">git</span> add -A    #提交所有已经修改的文件，包括删除新建文件
<span class="fu">git</span> add -u    #提交git上已跟踪的文件，不包括删除和新建的文件
<span class="fu">git</span> checkout -- <span class="op">&lt;</span>file<span class="op">&gt;</span>  # 撤销指定文件的修改
<span class="fu">git</span> reset  #回退git add 操作
<span class="fu">git</span> reset HEAD^ <span class="co">#撤销最近一次提交并保留修改</span>
<span class="fu">git</span> push origin +HEAD~1:master <span class="co">#撤销已经推送到远程仓库的提交</span>
<span class="fu">git</span> pull        #拉取远程仓库并合并到当前分支 git pull origin main
<span class="fu">git</span> fetch       #仅拉取远程仓库更新，不自动合并    git fetch --all
<span class="fu">git</span> reset       #回退提交   --soft（保留修改）、--hard（丢弃修改）
<span class="fu">git</span> diff        #查看工作区与暂存区的差异   git diff HEAD（比较最新提交）
<span class="fu">git</span> commit      #提交暂存区的修改   -m <span class="st">&quot;message&quot;</span>（添加提交信息）
<span class="fu">git</span> revert <span class="op">&lt;</span>commit<span class="op">&gt;</span> <span class="co">#撤销指定提交（生成新提交）  git revert HEAD（撤销最新提交）</span>
<span class="fu">git</span> rm <span class="op">&lt;</span>file<span class="op">&gt;</span>  删除本地和远程的文件
<span class="fu">git</span> rm --cached  <span class="op">&lt;</span>file<span class="op">&gt;</span> 删除远程的文件，保留本地
<span class="fu">git</span> remote -v    #查看git版本
<span class="fu">git</span> check <span class="op">&lt;</span>分支名<span class="op">&gt;</span>  #切换分支名
<span class="fu">git</span> branch  #查看当前分支</code></pre></div>
<ul>
<li>git仓库管理---提交更改流程：</li>
</ul>
<div class="sourceCode"><pre class="sourceCode sh"><code class="sourceCode bash"><span class="fu">git</span> init(如果要上传本地仓库)
<span class="co"># git clone https:...   或者克隆git上的代码</span>
<span class="co"># git checkout -b new-feature  为了避免直接在 main 或 master 分支上进行开发，通常会创建一个新的分支</span>
<span class="fu">git</span> status         #可以看工作区状态，看看有哪些文件有修改的
<span class="fu">git</span> add <span class="op">&lt;</span>file<span class="op">&gt;</span>         #添加到暂存区
<span class="fu">git</span> commit -m <span class="st">&quot;&quot;</span>       #提交更改
<span class="co">#git pull origin master 每次git push之前可以拉取远端更新并且合并到本地，以避免冲突</span>
<span class="co">#git fetch origin 也可以拉去最新的远端代码</span>
<span class="co">#git reset origin/kylinos-next --hard 强制本地代码和远程保持一致</span>
<span class="fu">git</span> push origin master <span class="co">#推送到远程仓库</span></code></pre></div>
<p>以上都是git的最基础的用法，但是作为内核开发的我们，仅仅学会这些还远远不够，因为内核代码是有很多个版本迭代的，所以对代码的版本管理非常重要，现在需要更深入的了解git的用法：</p>
<ul>
<li>分支管理</li>
</ul>
<p>分支管理是一个好东西，各个内核版本都可以延伸一个分支出来，分支更有利于团队协作，你修改分支代码并不会影响主线上的代码。</p>
<div class="sourceCode"><pre class="sourceCode sh"><code class="sourceCode bash"><span class="fu">git</span> branch          # 查看本地分支
<span class="fu">git</span> checkout <span class="op">&lt;</span>branch-name<span class="op">&gt;</span>  #切换分支
<span class="fu">git</span> branch <span class="op">&lt;</span>branch-name<span class="op">&gt;</span>        # 创建新分支
<span class="fu">git</span> branch -d <span class="op">&lt;</span>branch-name<span class="op">&gt;</span>     # 删除本地分支
<span class="fu">git</span> push origin --delete <span class="op">&lt;</span>branch-name<span class="op">&gt;</span>  # 删除远程分支
<span class="fu">git</span> branch -m <span class="op">&lt;</span>old-name<span class="op">&gt;</span> <span class="op">&lt;</span>new-name<span class="op">&gt;</span>  # 重命名本地分支
<span class="fu">git</span> merge <span class="op">&lt;</span>branch-name<span class="op">&gt;</span>  #合并分支到当前主分支，首先要执行git checkout切换到主分支</code></pre></div>
<ul>
<li>查看历史</li>
</ul>
<div class="sourceCode"><pre class="sourceCode sh"><code class="sourceCode bash"><span class="fu">git</span> log                 # 查看完整提交历史
<span class="fu">git</span> log -p <span class="op">&lt;</span>file<span class="op">&gt;</span>        # 查看某个文件的修改历史
<span class="fu">git</span> show <span class="op">&lt;</span>commit-id<span class="op">&gt;</span>    # 查看某次提交的详细信息
<span class="fu">git</span> log --grep=<span class="st">&quot;keyword&quot;</span>  # 根据提交信息搜索提交
<span class="fu">git</span> log -S <span class="st">&quot;keyword&quot;</span>      # 根据代码内容搜索提交
<span class="fu">git</span> log --follow --diff-filter=R --name-status -1 -- d  # 查看d文件的最近一次重命名提交</code></pre></div>
<ul>
<li>tag</li>
</ul>
<p>tag顾名思义就是给东西贴上标签，有了标签我们就可以更好的检索信息了,方便你追溯某个版本的代码。</p>
<div class="sourceCode"><pre class="sourceCode sh"><code class="sourceCode bash"><span class="fu">git</span> tag v1.0.0           # 在本地仓库创建名为 v1.0.0 的轻量标签,标签指向当前所在的提交,标签信息存储在 .git/refs/tags/v1.0.0 文件中，标签不包含额外元数据。
<span class="fu">git</span> tag -a v1.0.0 -m <span class="st">&quot;Release version 1.0.0&quot;</span>  # 在本地创建附注标签 v1.0.0，创建独立的标签对象（存储在 .git/objects）创建独立的标签对象（存储在 .git/objects）。

<span class="fu">git</span> push origin v1.0.0   # 推送指定标签
<span class="fu">git</span> push origin --tags   # 推送所有标签

<span class="fu">git</span> tag -d v1.0.0        # 删除本地标签
<span class="fu">git</span> push origin --delete v1.0.0  # 删除远程标签</code></pre></div>
<p>在 Git 中，标签(tag)是针对整个提交(commit)的，而不是针对单个文件的。这意味着你不能直接给单个文件打标签。</p>
<p>这篇主要介绍git业务方面的常用的方法：</p>
<ul>
<li>如何查看一个函数的第一次提交记录：</li>
</ul>
<div class="sourceCode"><pre class="sourceCode sh"><code class="sourceCode bash"><span class="co">#拿smb2_parse_contexts这个函数举例子</span>
<span class="bu">cd</span>  主线分支
<span class="fu">git</span> blame fs/smb/client/smb2pdu.c <span class="kw">|</span> <span class="fu">grep</span> smb2_parse_contexts  #会弹出commit-id 找到定义函数的commit-id
<span class="fu">git</span> show  <span class="op">&lt;</span>commit-id<span class="op">&gt;</span>                #查看这个commit是否是第一次提交
<span class="fu">git</span> log --oneline  <span class="op">&lt;</span>commit-id<span class="op">&gt;</span>       #如果不是第一次提交，查看这个commit-id的前一个提交
<span class="fu">git</span> checkout <span class="op">&lt;</span>commit-id<span class="op">&gt;</span>             #回退到之前版本
<span class="co">#然后再重复第二个步骤</span></code></pre></div>
<p>这里重点讲一下git blame的用法：</p>
<p>git blame 是 Git 中用于查看文件每一行的修改历史记录的命令。它的作用是追踪文件中每一行的最后一次修改是谁做的，修改的时间是何时，修改的提交信息是什么。</p>
<div class="sourceCode"><pre class="sourceCode sh"><code class="sourceCode bash"><span class="co">#比如想查看某一个文件的改动记录，可以用</span>
<span class="fu">git</span> blame <span class="op">&lt;</span>file<span class="op">&gt;</span> xxx.c   #会输出每一行代码的作者、提交哈希和提交时间，格式如下：
^<span class="ex">1da177e4c3f4</span> (Linus Torvalds          2005-04-16 15:20:36 -0700     1) <span class="ex">/*</span>
<span class="co">#git blame 有一些常用的参数</span>
<span class="ex">-L</span> <span class="op">&lt;</span>start<span class="op">&gt;</span>,<span class="op">&lt;</span>end<span class="op">&gt;</span> ：仅查看文件的某个行范围。
    <span class="fu">git</span> blame -L 10,20 xxx.c <span class="co">#查看xxx.c文件的第 10 行到第 20 行的代码历史</span>
<span class="ex">-C</span>：查找代码移动或复制的历史。此选项会查找哪些行可能是从其他地方复制或移动过来的
    <span class="fu">git</span> blame -C xxx.c
<span class="ex">-f</span>：在输出中包括文件路径，默认情况下，git blame 只会显示文件内容，不包含文件名
    <span class="fu">git</span> blame -f xxx.c
<span class="ex">-s</span>：只显示提交的哈希，不显示其他信息。
    <span class="fu">git</span> blame -s xxx.c <span class="co">#只会输出相关的哈希值。</span></code></pre></div>
<ul>
<li>合入补丁操作流程</li>
</ul>
<div class="sourceCode"><pre class="sourceCode sh"><code class="sourceCode bash">
<span class="bu">cd</span> kylinx-4.19 <span class="co">#进入4.19分支</span>
<span class="fu">git</span> branch    #查看是否是 kylinos-next分支
<span class="fu">git</span> checkout kylinos-next  # 如果不在目标分支，切换到 kylinos-next
<span class="fu">git</span> fetch origin <span class="co"># 从远程拉取代码到本地</span>
<span class="fu">git</span> reset origin/kylinos-next --hard <span class="co"># 强制本地代码和远程保持一致</span>
<span class="fu">git</span> show  <span class="op">&lt;</span>commit-id<span class="op">&gt;</span>  #从工单信息获取需要修复的CVE列表 <span class="op">&lt;</span>commit-id<span class="op">&gt;</span> 是上游修复补丁
<span class="fu">git</span> show --stat <span class="op">&lt;</span>commit-id<span class="op">&gt;</span>    #可以查看某个文件修改的统计
<span class="fu">git</span> log  --grep=<span class="st">&quot;&lt;修改信息&gt;&quot;</span>  #查看是否补丁已经合入？

<span class="fu">git</span> remote -v  #如果需要合入补丁,就查看上游
<span class="fu">git</span> log --all --grep=<span class="st">&quot;CVE-XXXX-XXXXX&quot;</span> <span class="co">#根据CVE查看上游是否已经生成了补丁,是，则从上游或在openeular生成补丁</span>
<span class="fu">git</span> format-patch -1 <span class="op">&lt;</span>commit-id<span class="op">&gt;</span>  #根据上游和openeular生成补丁

<span class="fu">git</span> log -1 <span class="op">&lt;</span>hash<span class="op">&gt;</span> --format=<span class="st">&quot;%P&quot;</span>  #查询父提交
<span class="fu">git</span> log --graph --oneline <span class="op">&lt;</span>commit-id<span class="op">&gt;</span>~5..<span class="op">&lt;</span>commit-id<span class="op">&gt;</span>   # 查看该 commit 是否依赖其他补丁
<span class="fu">git</span> am 001-xxx.patch --reject <span class="co">#合入补丁并且生成冲突文件.rej</span>
<span class="fu">git</span> status -s <span class="co">#查看合入补丁的状态</span>
<span class="fu">git</span> add -u   #合并已经解决的文件
<span class="ex">vim</span> <span class="op">&lt;</span>冲突文件.rej<span class="op">&gt;</span>  #打开冲突文件.rej
:<span class="ex">vsp</span> <span class="op">&lt;</span>冲突文件<span class="op">&gt;</span>      #vim两个窗口打开文件对比分析
<span class="co">#解决冲突后再次合并</span>
<span class="fu">git</span> add <span class="op">&lt;</span>已解决的文件<span class="op">&gt;</span>
<span class="fu">git</span> am --continue  # 完成补丁应用

<span class="co">#合并完成后，编译测试</span>
<span class="fu">rm</span> x86_64-build -rf <span class="kw">&amp;&amp;</span> <span class="fu">mkdir</span> x86_64-build
<span class="fu">cp</span> arch/x86/configs/kylinos_generic_defconfig x86_64-build/.config
<span class="fu">make</span> O=x86_64-build menuconfig <span class="co"># 比如编译nfs模块，搜索 nfs_fs</span>
<span class="bu">time</span> make O=x86_64-build bzImage -j<span class="kw">`</span><span class="ex">nproc</span><span class="kw">`</span>

<span class="co">#提交更改</span>
<span class="fu">git</span> commit --amend  # 添加测试记录
<span class="fu">git</span> push origin cve-2024-xxxx-fix</code></pre></div>
</body>
</html>
